#include "tp1107_app.h"
#include "tp1107_api.h"
#include "tp1107_board.h"

#if (_NETWOK_MODLE_TYPE_ == _TP1107_MODULE_) && (_NETWOK_FUNCTION_ENABLE_)

static Tp1107BitStatus_t Tp1107BitStatus = {0};
static Tp1107HardwareAttributes_t Tp1107HardwareAttributes = {0};

void Tp1107CommunicationsInitialization(void)
{
  memset(&Tp1107BitStatus, 0, sizeof(Tp1107BitStatus_t));
  Tp1107BitStatus.StepsOfSending = TP1107_INTO_COMMAND_MODE;
}

void Tp1107FilterKeywords(const uint8_t *pMessagePacket, uint16_t *pMessageSize)
{
  char *pKeywordOffset = NULL;
  char *pDataPacket = (char *)pMessagePacket;

  if (pMessagePacket != NULL)
  {
    pKeywordOffset = strstr(pDataPacket, "=== UNB System Startup ===\r\n");
    if (pKeywordOffset != NULL)
    {
      memset(pKeywordOffset, 0, strlen("=== UNB System Startup ===\r\n"));
      *pMessageSize -= strlen("=== UNB System Startup ===\r\n");
    }

    pKeywordOffset = strstr(pDataPacket, "[A]goToSleep\r\n");
    if (pKeywordOffset != NULL)
    {
      memset(pKeywordOffset, 0, strlen("[A]goToSleep\r\n"));
      *pMessageSize -= strlen("[A]goToSleep\r\n");
    }

    pKeywordOffset = strstr(pDataPacket, "[A]goToAwake\r\n");
    if (pKeywordOffset != NULL)
    {
      memset(pKeywordOffset, 0, strlen("[A]goToAwake\r\n"));
      *pMessageSize -= strlen("[A]goToAwake\r\n");
    }
  }
}

bool Tp1107BuildSelfTestMessage(uint8_t *pMessageOut, uint16_t *pSizeOut, uint32_t *pResponseTimeOut)
{
  bool MessageConstructionState = false;

  if ((pMessageOut != NULL) && (pSizeOut != NULL) && (pResponseTimeOut != NULL))
  {
    switch (Tp1107BitStatus.StepsOfSending)
    {
    case TP1107_GET_VERSION_NUMBER:
      MessageConstructionState = Tp1107BuildQueryFirmwareVersionNumberMessage(pMessageOut, pSizeOut);
      break;

    case TP1107_GET_SERIAL_NUMBER:
      MessageConstructionState = Tp1107BuildQueryModuleESNMessage(pMessageOut, pSizeOut);
      break;

    case TP1107_EXIT_COMMAND_MODE:
      MessageConstructionState = Tp1107BuildExitingCommandModeMessage(pMessageOut, pSizeOut);
      break;

    default:
      MessageConstructionState = Tp1107BuildEnteringCommandModeMessage(pMessageOut, pSizeOut);
      break;
    }
  }

  return MessageConstructionState;
}

bool Tp1107BuildDeviceResetMessage(uint8_t *pMessageOut, uint16_t *pSizeOut, uint32_t *pResponseTimeOut)
{
  bool MessageConstructionState = false;

  if ((pMessageOut != NULL) && (pSizeOut != NULL) && (pResponseTimeOut != NULL))
  {
    switch (Tp1107BitStatus.StepsOfSending)
    {
    case TP1107_FACTORY_RESET:
      MessageConstructionState = Tp1107BuildFactoryResetMessage(pMessageOut, pSizeOut);
      break;

    default:
      MessageConstructionState = Tp1107BuildEnteringCommandModeMessage(pMessageOut, pSizeOut);
      break;
    }
  }

  return MessageConstructionState;
}

bool Tp1107BuildInitiateNetAttachmentMessage(uint8_t *pMessageOut, uint16_t *pSizeOut, uint32_t *pResponseTimeOut)
{
  bool MessageConstructionState = false;

  if ((pMessageOut != NULL) && (pSizeOut != NULL) && (pResponseTimeOut != NULL))
  {
    switch (Tp1107BitStatus.StepsOfSending)
    {
    case TP1107_CONFIG_SEARCH_TIMEOUT:
    {
      uint8_t SearchNetworkTimeout = 0;
      if (Tp1107GetSearchNetworkTimeout(&SearchNetworkTimeout) != true)
      {
        SearchNetworkTimeout = TP1107_MIX_NETWORK_TIMEOUT;
      }

      MessageConstructionState = Tp1107BuildSearchNetworkTimeoutMessage(pMessageOut, pSizeOut, SearchNetworkTimeout);
    }
    break;

    case TP1107_CONFIG_ADAPTIVE_EMISSION_POWER:
    {
      bool AdaptiveEmissionPowerState = Tp1107GetEmissionPower(NULL) ? false : true;
      MessageConstructionState = Tp1107BuildConfiguringAdaptiveEmissionPowerMessage(pMessageOut, pSizeOut, AdaptiveEmissionPowerState);
    }
    break;

    case TP1107_CONFIG_EMISSION_POWER:
    {
      int TxPower = 0;
      if (Tp1107GetEmissionPower(&TxPower) != true)
      {
        TxPower = TP1107_MAX_EMISSION_POWER;
      }

      MessageConstructionState = Tp1107BuildConfiguringEmissionPowerMessage(pMessageOut, pSizeOut, TxPower);
    }
    break;

    case TP1107_CONFIG_AUTO_SCAN_FREQUENCY_RANGE:
    {
      bool AutoScanFrequencyRangeState = Tp1107GetFrequencyRange(NULL) ? false : true;
      MessageConstructionState = Tp1107BuildAutoFrequencyScanningMessage(pMessageOut, pSizeOut, AutoScanFrequencyRangeState);
    }
    break;

    case TP1107_CONFIG_FREQUENCY_RANGE:
    {
      uint8_t FreqRange = 0;
      if (Tp1107GetFrequencyRange(&FreqRange) != true)
      {
        FreqRange = TP1107_MAX_FREQUENCY_RANGE;
      }

      MessageConstructionState = Tp1107BuildConfiguringWorkingFrequencyMessage(pMessageOut, pSizeOut, FreqRange);
    }
    break;

    case TP1107_CONFIG_ADMISSION_MODE:
    {
      MessageConstructionState = Tp1107BuildConfiguringAdmissionModeMessage(pMessageOut, pSizeOut, true);
    }
    break;

    case TP1107_DEVICE_RESET:
    {
      MessageConstructionState = Tp1107BuildModuleRebootMessage(pMessageOut, pSizeOut);
    }
    break;

    case TP1107_WAIT_NETWORK_ATTACHMENT:
    {
      MessageConstructionState = Tp1107BuildCheckingNetworkstatusMessage(pMessageOut, pSizeOut);
    }
    break;

    case TP1107_GET_LINK_STATUS:
    {
      MessageConstructionState = Tp1107BuildGetCurrentLinkStateMessage(pMessageOut, pSizeOut);
    }
    break;

    case TP1107_GET_COMM_FREQUENCIES:
    {
      MessageConstructionState = Tp1107BuildQueryCurrentFrequencyInformationMessage(pMessageOut, pSizeOut);
    }
    break;

    case TP1107_EXIT_COMMAND_MODE:
    {
      MessageConstructionState = Tp1107BuildExitingCommandModeMessage(pMessageOut, pSizeOut);
    }
    break;

    default:
    {
      MessageConstructionState = Tp1107BuildEnteringCommandModeMessage(pMessageOut, pSizeOut);
    }
    break;
    }
  }

  return MessageConstructionState;
}

bool Tp1107BuildForceExitCommandModeMessage(uint8_t *pMessageOut, uint16_t *pSizeOut, uint32_t *pResponseTimeOut)
{
  bool MessageConstructionState = false;

  if ((pMessageOut != NULL) && (pSizeOut != NULL) && (pResponseTimeOut != NULL))
  {
    switch (Tp1107BitStatus.StepsOfSending)
    {
    case TP1107_EXIT_COMMAND_MODE:
      MessageConstructionState = Tp1107BuildExitingCommandModeMessage(pMessageOut, pSizeOut);
      break;

    default:
      MessageConstructionState = Tp1107BuildEnteringCommandModeMessage(pMessageOut, pSizeOut);
      break;
    }
  }

  return MessageConstructionState;
}

uint8_t Tp1107ParsingIncomingMessageValidity(const void *pRxMessage, uint16_t MessageLenght)
{
  return Tp1107AuthenticationMessageType(pRxMessage, MessageLenght);
}

uint8_t Tp1107ParsingSelfTestMessage(const void *pDataIn)
{
  uint8_t ParsingResults = TP1107_EXECUTE_ERROR;
  Tp1107MessageParsingResult_t ParsingState = TP1107_PARSING_ERROR;

  if (pDataIn != NULL)
  {
    switch (Tp1107BitStatus.StepsOfSending)
    {
    case TP1107_INTO_COMMAND_MODE:
    {
      ParsingState = Tp1107ParsingEnteringCommandModeMessage(pDataIn);
      if (ParsingState == TP1107_PARSING_SUCCESS)
      {
        ParsingResults = TP1107_EXECUTE_SUCCESS;
        Tp1107BitStatus.StepsOfSending = TP1107_GET_VERSION_NUMBER;
      }
    }
    break;

    case TP1107_GET_VERSION_NUMBER:
    {
      memset(Tp1107HardwareAttributes.VersionNumber, 0, TP1107_NUMBER_OF_VERSION);

      ParsingState = Tp1107ParsingQueryFirmwareVersionNumberMessage(pDataIn, Tp1107HardwareAttributes.VersionNumber, NULL, NULL, NULL);
      if (ParsingState == TP1107_PARSING_SUCCESS)
      {
        ParsingResults = TP1107_EXECUTE_SUCCESS;
        Tp1107BitStatus.StepsOfSending = TP1107_GET_SERIAL_NUMBER;
      }
    }
    break;

    case TP1107_GET_SERIAL_NUMBER:
    {
      memset(Tp1107HardwareAttributes.ModelSerialNumber, 0, TP1107_NUMBER_OF_SERIAL_NUMBER);

      ParsingState = Tp1107ParsingQueryModuleESNMessage(pDataIn, Tp1107HardwareAttributes.ModelSerialNumber);
      if (ParsingState == TP1107_PARSING_SUCCESS)
      {
        ParsingResults = TP1107_EXECUTE_SUCCESS;
        Tp1107BitStatus.StepsOfSending = TP1107_EXIT_COMMAND_MODE;
      }
    }
    break;

    case TP1107_EXIT_COMMAND_MODE:
    {
      ParsingState = Tp1107ParsingExitingCommandModeMessage(pDataIn);
      if (ParsingState == TP1107_PARSING_SUCCESS)
      {
        ParsingResults = TP1107_EXECUTE_OVER;
        Tp1107BitStatus.StepsOfSending = TP1107_ALL_COMMAND_EXECUTED;
      }
    }
    break;

    default:
      break;
    }
  }

  return ParsingResults;
}

uint8_t Tp1107ParsingDeviceResetMessage(const void *pDataIn)
{
  uint8_t ParsingResults = TP1107_EXECUTE_ERROR;
  Tp1107MessageParsingResult_t ParsingState = TP1107_PARSING_ERROR;

  if (pDataIn != NULL)
  {
    switch (Tp1107BitStatus.StepsOfSending)
    {
    case TP1107_INTO_COMMAND_MODE:
    {
      ParsingState = Tp1107ParsingEnteringCommandModeMessage(pDataIn);
      if (ParsingState == TP1107_PARSING_SUCCESS)
      {
        ParsingResults = TP1107_EXECUTE_SUCCESS;
        Tp1107BitStatus.StepsOfSending = TP1107_FACTORY_RESET;
      }
    }
    break;

    case TP1107_FACTORY_RESET:
    {
      ParsingState = Tp1107ParsingFactoryResetMessage(pDataIn);
      if (ParsingState == TP1107_PARSING_SUCCESS)
      {
        ParsingResults = TP1107_EXECUTE_OVER;
        Tp1107BitStatus.StepsOfSending = TP1107_ALL_COMMAND_EXECUTED;
      }
    }
    break;

    default:
      break;
    }
  }

  return ParsingResults;
}

uint8_t Tp1107ParsingInitiateNetAttachmentMessage(const void *pDataIn)
{
  Tp1107MessageParsingResult_t ParsingState = TP1107_PARSING_ERROR;
  uint8_t ParsingResults = TP1107_EXECUTE_ERROR, NetAttachmentStatus = 0;

  if (pDataIn != NULL)
  {
    switch (Tp1107BitStatus.StepsOfSending)
    {
    case TP1107_INTO_COMMAND_MODE:
    {
      ParsingState = Tp1107ParsingEnteringCommandModeMessage(pDataIn);
      if (ParsingState == TP1107_PARSING_SUCCESS)
      {
        ParsingResults = TP1107_EXECUTE_SUCCESS;
        Tp1107BitStatus.StepsOfSending = TP1107_CONFIG_SEARCH_TIMEOUT;
      }
    }
    break;

    case TP1107_CONFIG_SEARCH_TIMEOUT:
    {
      ParsingState = Tp1107PrasingSearchNetworkTimeoutMessage(pDataIn);
      if (ParsingState == TP1107_PARSING_SUCCESS)
      {
        ParsingResults = TP1107_EXECUTE_SUCCESS;
        Tp1107BitStatus.StepsOfSending = TP1107_CONFIG_ADAPTIVE_EMISSION_POWER;
      }
    }
    break;

    case TP1107_CONFIG_ADAPTIVE_EMISSION_POWER:
    {
      ParsingState = Tp1107ParsingConfiguringAdaptiveEmissionPowerMessage(pDataIn);
      if (ParsingState == TP1107_PARSING_SUCCESS)
      {
        ParsingResults = TP1107_EXECUTE_SUCCESS;
        Tp1107BitStatus.StepsOfSending = (Tp1107GetEmissionPower(NULL) == true) ? TP1107_CONFIG_EMISSION_POWER : TP1107_CONFIG_AUTO_SCAN_FREQUENCY_RANGE;
      }
    }
    break;

    case TP1107_CONFIG_EMISSION_POWER:
    {
      ParsingState = Tp1107ParsingConfiguringEmissionPowerMessage(pDataIn);
      if (ParsingState == TP1107_PARSING_SUCCESS)
      {
        ParsingResults = TP1107_EXECUTE_SUCCESS;
        Tp1107BitStatus.StepsOfSending = TP1107_CONFIG_AUTO_SCAN_FREQUENCY_RANGE;
      }
    }
    break;

    case TP1107_CONFIG_AUTO_SCAN_FREQUENCY_RANGE:
    {
      ParsingState = Tp1107ParsingAutoFrequencyScanningessage(pDataIn);
      if (ParsingState == TP1107_PARSING_SUCCESS)
      {
        ParsingResults = TP1107_EXECUTE_SUCCESS;
        Tp1107BitStatus.StepsOfSending = (Tp1107GetFrequencyRange(NULL) == true) ? TP1107_CONFIG_FREQUENCY_RANGE : TP1107_CONFIG_ADMISSION_MODE;
      }
    }
    break;

    case TP1107_CONFIG_FREQUENCY_RANGE:
    {
      ParsingState = Tp1107ParsingConfiguringWorkingFrequencyMessage(pDataIn);
      if (ParsingState == TP1107_PARSING_SUCCESS)
      {
        ParsingResults = TP1107_EXECUTE_SUCCESS;
        Tp1107BitStatus.StepsOfSending = TP1107_CONFIG_ADMISSION_MODE;
      }
    }
    break;

    case TP1107_CONFIG_ADMISSION_MODE:
    {
      ParsingState = Tp1107ParsingConfiguringAdmissionModeMessage(pDataIn);
      if (ParsingState == TP1107_PARSING_SUCCESS)
      {
        ParsingResults = TP1107_EXECUTE_SUCCESS;
        Tp1107BitStatus.StepsOfSending = TP1107_DEVICE_RESET;
      }
    }
    break;

    case TP1107_DEVICE_RESET:
    {
      ParsingState = Tp1107ParsingModuleRebootMessage(pDataIn);
      if (ParsingState == TP1107_PARSING_SUCCESS)
      {
        ParsingResults = TP1107_EXECUTE_SUCCESS;
        Tp1107BitStatus.StepsOfSending = TP1107_WAIT_NETWORK_ATTACHMENT;
      }
    }
    break;

    case TP1107_WAIT_NETWORK_ATTACHMENT:
    {
      ParsingState = Tp1107ParsingCheckingNetworkstatusMessage(pDataIn, &NetAttachmentStatus);
      if (ParsingState == TP1107_PARSING_SUCCESS)
      {
        ParsingResults = TP1107_EXECUTE_RETRY;

        if (NetAttachmentStatus == TP1107_JOINED)
        {
          ParsingResults = TP1107_EXECUTE_SUCCESS;
          Tp1107BitStatus.StepsOfSending = TP1107_GET_LINK_STATUS;
        }
      }
    }
    break;

    case TP1107_GET_LINK_STATUS:
    {
      Tp1107HardwareAttributes.Rssi = 0;

      ParsingState = Tp1107ParsingGetCurrentLinkStateMessage(pDataIn, &Tp1107HardwareAttributes.Rssi, NULL, NULL, NULL);
      if (ParsingState == TP1107_PARSING_SUCCESS)
      {
        ParsingResults = TP1107_EXECUTE_SUCCESS;
        Tp1107BitStatus.StepsOfSending = TP1107_GET_COMM_FREQUENCIES;
      }
    }
    break;

    case TP1107_GET_COMM_FREQUENCIES:
    {
      Tp1107HardwareAttributes.UplinkFrequency = 0;
      Tp1107HardwareAttributes.DownlinkFrequency = 0;

      ParsingState = Tp1107ParsingQueryCurrentFrequencyInformationMessage(pDataIn, &Tp1107HardwareAttributes.UplinkFrequency, &Tp1107HardwareAttributes.DownlinkFrequency);
      if (ParsingState == TP1107_PARSING_SUCCESS)
      {
        ParsingResults = TP1107_EXECUTE_SUCCESS;
        Tp1107BitStatus.StepsOfSending = TP1107_EXIT_COMMAND_MODE;
      }
    }
    break;

    case TP1107_EXIT_COMMAND_MODE:
    {
      ParsingState = Tp1107ParsingExitingCommandModeMessage(pDataIn);
      if (ParsingState == TP1107_PARSING_SUCCESS)
      {
        ParsingResults = TP1107_EXECUTE_OVER;
        Tp1107BitStatus.StepsOfSending = TP1107_ALL_COMMAND_EXECUTED;
      }
    }
    break;

    default:
      break;
    }
  }

  return ParsingResults;
}

uint8_t Tp1107ParsingForceExitCommandModeMessage(const void *pDataIn)
{
  uint8_t ParsingResults = TP1107_EXECUTE_ERROR;

  if (pDataIn != NULL)
  {
    switch (Tp1107BitStatus.StepsOfSending)
    {
    case TP1107_EXIT_COMMAND_MODE:
    {
      ParsingResults = TP1107_EXECUTE_OVER;
      Tp1107BitStatus.StepsOfSending = TP1107_ALL_COMMAND_EXECUTED;
    }
    break;

    default:
    {
      ParsingResults = TP1107_EXECUTE_SUCCESS;
      Tp1107BitStatus.StepsOfSending = TP1107_EXIT_COMMAND_MODE;
    }
    break;
    }
  }

  return ParsingResults;
}

uint8_t Tp1107GetWirelessQuality(void)
{
  return (uint8_t)abs(Tp1107HardwareAttributes.Rssi);
}

void Tp1107GetFirmwareVersionNumber(void *pVersion)
{
  if (pVersion != NULL)
  {
    strcpy((char *)pVersion, Tp1107HardwareAttributes.VersionNumber);
  }
}

void Tp1107GetSerialNumber(void *pSerialNumber)
{
  if (pSerialNumber != NULL)
  {
    strcpy((char *)pSerialNumber, Tp1107HardwareAttributes.ModelSerialNumber);
  }
}

#endif
